﻿using System;
using System.Collections.Generic;
using sdd.subsystems.display;
using sdd.subsystems.ui;

namespace sdd.subsystems.ui.screens
{
    class ScrMenuMain : IScreen
    {

    #region IScreen Implementation
        private object _UpdateLock = new Object();
        private int _SelectorPosition = 0;
        private int _SubItemsStartPos = 0;
        private MenuItem _CurrentTopLevelMenu;
        private int _CurrentTopLevelMenuId;      

        public ScrMenuMain()
        {
           
        }

        ~ScrMenuMain()
        {

        }

        public string ScreenName { get { return "Main Menu"; } }
        
        public int SelectorPosition
        {
            get { return _SelectorPosition; }
            set
            {
                _SelectorPosition = value;
                DrawSelector();
            }
        }
        
        public IDisplay Display { get; set; }
        public ScreenManager Manager { get; set; }
        
        public void Initialize()
        {
            Display.InitializeTextWindow(ScreenManager.WINDOW_MENU_SUBITEMS, 8, 26, 185, 64, ScreenManager.FONT_PROP_SMALL, 1, 1, 0);
            _CurrentTopLevelMenu = Manager.Menus.Menu("Application");
            _CurrentTopLevelMenuId = 1;
        }

        public void Show()
        {
            DrawHeader();
            DrawRootMenu();
            DrawSubMenu(_CurrentTopLevelMenu);
            DrawSelector();
        }

        public void Hide()
        {
            //throw new NotImplementedException();
        }

        public void ProcessKeyPadEvent(KeypadEventArgs keyPadEventArgs)
        {
            var SelectedItem = GetSelectedSubMenuItem();
            var SelectedMenu = GetSelectedTopMenuItem();

            switch (keyPadEventArgs.Key)
            {
                case KeypadKeys.Down:
                    ProcessCmdDown();
                    break;

                case KeypadKeys.Up:
                    ProcessCmdUp();
                    break;

                case KeypadKeys.Center:
                    ProcessCmdCenter(SelectedItem);
                    break;

                case KeypadKeys.Left:
                    ProcessCmdLeft(SelectedItem);
                    break;

                case KeypadKeys.Right:
                    ProcessCmdRight(SelectedItem);
                    break;
                
                case KeypadKeys.FunctionUpper:
                    Manager.Buzz();
                    Manager.Show(Manager.PreviousScreen);
                    break;
            }
        }
    #endregion

    #region Private Methods

        private void ProcessCmdCenter(MenuItem SelectedItem)
        {
            if (SelectedItem is LinkMenuItem)
            {
                Manager.Buzz();
                LinkMenuItem lnk = (LinkMenuItem)(SelectedItem);
                Manager.Show(lnk.LinkedScreen);
            }
            else if (SelectedItem is IToggleableMenutItem)
            {
                Manager.Buzz();
                IToggleableMenutItem tog = (IToggleableMenutItem)(SelectedItem);
                tog.Toggle();
                DrawSubMenu(_CurrentTopLevelMenu);
            }
            else if (SelectedItem is IClickableMenuItem)
            {
                Manager.Buzz();
                IClickableMenuItem clk = (IClickableMenuItem)(SelectedItem);
                clk.Click();
            }
        }

        private void ProcessCmdLeft(MenuItem SelectedItem)
        {
            if (SelectedItem == null)
            {
                if (_CurrentTopLevelMenuId > 1)
                {
                    _CurrentTopLevelMenuId--;
                    _CurrentTopLevelMenu = GetSelectedTopMenuItem();
                    DrawRootMenu();
                    DrawSubMenu(_CurrentTopLevelMenu);
                    Manager.Buzz();
                }
            }
            if (SelectedItem is IToggleableMenutItem)
            {
                Manager.Buzz();
                IToggleableMenutItem togl = (IToggleableMenutItem)SelectedItem;
                togl.Toggle();
                DrawSubMenu(_CurrentTopLevelMenu);
            }
            if (SelectedItem is IBrowseableMenuItem)
            {
                Manager.Buzz();
                IBrowseableMenuItem brws = (IBrowseableMenuItem)SelectedItem;
                brws.Previous();
                DrawSubMenu(_CurrentTopLevelMenu);
            }
            if (SelectedItem is ICountableMenuItem)
            {
                ICountableMenuItem cnt = (ICountableMenuItem)SelectedItem;
                try
                {
                    cnt.Decrease();
                    Manager.Buzz();
                    DrawSubMenu(_CurrentTopLevelMenu);
                }
                catch (ArgumentOutOfRangeException)
                {
                    // couldn't decrease, don't buzz
                }   
            }
        }

        private void ProcessCmdRight(MenuItem SelectedItem)
        {
            if (SelectedItem == null)
            {
                if (_CurrentTopLevelMenuId < Manager.Menus.Count)
                {
                    Manager.Buzz();
                    _CurrentTopLevelMenuId++;
                    _CurrentTopLevelMenu = GetSelectedTopMenuItem();
                    DrawRootMenu();
                    DrawSubMenu(_CurrentTopLevelMenu);
                }
            }
            if (SelectedItem is IToggleableMenutItem)
            {
                Manager.Buzz();
                IToggleableMenutItem togl = (IToggleableMenutItem)SelectedItem;
                togl.Toggle();
                DrawSubMenu(_CurrentTopLevelMenu);
            }
            if (SelectedItem is IBrowseableMenuItem)
            {
                Manager.Buzz();
                IBrowseableMenuItem brws = (IBrowseableMenuItem)SelectedItem;
                brws.Next();
                DrawSubMenu(_CurrentTopLevelMenu);
            }
            if (SelectedItem is ICountableMenuItem)
            {
                ICountableMenuItem cnt = (ICountableMenuItem)SelectedItem;
                try
                {
                    cnt.Increase();
                    Manager.Buzz();
                    DrawSubMenu(_CurrentTopLevelMenu);
                }
                catch (ArgumentOutOfRangeException)
                {
                    // could not increase, don't buzz
                }                
            }
        }

        private void ProcessCmdUp()
        {
            if (SelectorPosition == 1)
            {
               if (_SubItemsStartPos > 0)
               {
                   Manager.Buzz();
                   _SubItemsStartPos--;
                   DrawSubMenu(_CurrentTopLevelMenu, _SubItemsStartPos);
               }
               else
               {
                   // move to top level selection (selector position 0)
                   SelectorPosition--;
                   Manager.Buzz();
               }
            }
            else if (SelectorPosition > 1)
            {
                SelectorPosition--;
                Manager.Buzz();
            }
            else
            {
                if (_SubItemsStartPos > 0)
                {
                    Manager.Buzz();
                    _SubItemsStartPos--;
                    DrawSubMenu(_CurrentTopLevelMenu, _SubItemsStartPos);
                }
            }
        }

        private void ProcessCmdDown()
        {
            if (SelectorPosition < 4 & SelectorPosition < _CurrentTopLevelMenu.SubItems.Count)
            {
                Manager.Buzz();
                SelectorPosition++;
            }
            else
            {
                if (_CurrentTopLevelMenu.SubItems.Count > 4)
                {
                    if (_SubItemsStartPos + 4 < _CurrentTopLevelMenu.SubItems.Count)
                    {
                        Manager.Buzz();
                        _SubItemsStartPos++;
                        DrawSubMenu(_CurrentTopLevelMenu, _SubItemsStartPos);
                    }
                }
            }
        }

        private MenuItem GetSelectedTopMenuItem()
        {
            int i = 1;
            foreach (MenuItem item in Manager.Menus)
            {
                if (_CurrentTopLevelMenuId == i)
                {
                    return item;
                    
                }
                i++;
            }
            return null;
        }

        private MenuItem GetSelectedSubMenuItem()
        {
            int i = -1;
            MenuItem[] SubItems = new MenuItem[_CurrentTopLevelMenu.SubItems.Count];
            foreach (MenuItem item in _CurrentTopLevelMenu.SubItems)
            {
                i++;
                SubItems[i] = item;
            }

            int selectedEntryNo = _SubItemsStartPos + SelectorPosition - 1;
            if (selectedEntryNo >= 0)
            {
                return SubItems[selectedEntryNo];
            }
            else
            {
                return null;
            }
        }

        private void DrawHeader()
        {
            lock (_UpdateLock)
            {
                Display.SetCursorCoordinate(0, 0);
                Display.SetCurrentFont(ScreenManager.FONT_PROP_LARGE);
                Display.WriteText("Main Menu");
                Display.DrawLine(0, 14, 192, 14);
            }
        }

        private void DrawRootMenu()
        {
            lock (_UpdateLock)
            {
                Display.DrawFilledRectangle(0, 8, 18, 192, 26);
                Display.SetCursorCoordinate(8, 18);
                Display.SetCurrentFont(ScreenManager.FONT_PROP_SMALL);
                Display.WriteText(_CurrentTopLevelMenu.Name);
            }
        }

        private void DrawSubMenu(MenuItem parentMenu, int startItemNo = 0)
        {
            lock (_UpdateLock)
            {
                Display.ClearTextWindow(ScreenManager.WINDOW_MENU_SUBITEMS);
                Display.SetTextWindow(ScreenManager.WINDOW_MENU_SUBITEMS);
                Display.DrawLine(8, 27, 192, 27);
                int i = 0;
                i = 0;
                for (int j = startItemNo; (j < parentMenu.SubItems.Count & j < startItemNo + 4); j++)
                {
                    // print item name
                    Display.SetCursorCoordinate(8, (byte)(31 + (i * 8)));
                    Display.WriteText(parentMenu.SubItems[j].Name);
                    // print item value
                    Display.SetCursorCoordinate(100, (byte)(31 + (i * 8)));
                    var menuItem = parentMenu.SubItems[j];
                    if (menuItem is IPrintableValueMenuItem)
                    {
                        IPrintableValueMenuItem prnt = (IPrintableValueMenuItem)menuItem;
                        Display.WriteText(prnt.Print());
                    }
                    i++;
                }
                Display.SetTextWindow(ScreenManager.WINDOW_DEFAULT);
            }
        }

        private void DrawSelector()
        {
            lock (_UpdateLock)
            {
                // clear selector area
                Display.DrawFilledRectangle(0, 0, 15, 7, 64);
                // draw new selector
                Display.SetCurrentFont(ScreenManager.FONT_MONO_AUDIOSYMBOLS);
                switch (SelectorPosition)
                {
                    case 0:
                        // top level menu selection
                        Display.SetCursorCoordinate(0, 18);
                        Display.WriteText("A");
                        break;
                    default:
                        // subitem menu selection
                        Display.SetCursorCoordinate(0, (byte)(31 + ((SelectorPosition - 1) * 8)));
                        Display.WriteText("A");
                        break;
                }
            }
        }

    #endregion


        public apps.IApplication Application { set; get; }
    }
}
